﻿Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.Runtime.DebugEngine

Namespace System.Workflow.Activities
    <ToolboxBitmap(GetType(ParallelActivity), "Resources.Parallel.png"), SRCategory("Standard"), SRDescription("ParallelActivityDescription"), ToolboxItem(GetType(ParallelToolboxItem)), Designer(GetType(ParallelDesigner), GetType(IDesigner)), ActivityValidator(GetType(ParallelValidator)), WorkflowDebuggerStepping(WorkflowDebuggerSteppingOption.Concurrent)> _
    Public NotInheritable Class ParallelActivity
        Inherits CompositeActivity
        Implements IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs)
        ' Methods
        Public Sub New()
        End Sub

        Public Sub New(ByVal name As String)
            MyBase.New(name)
        End Sub

        Protected Overrides Function Cancel(ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            Dim flag As Boolean = True
            Dim i As Integer
            For i = 0 To MyBase.EnabledActivities.Count - 1
                Dim activity As Activity = MyBase.EnabledActivities.Item(i)
                If (activity.ExecutionStatus = ActivityExecutionStatus.Executing) Then
                    executionContext.CancelActivity(activity)
                    flag = False
                ElseIf ((activity.ExecutionStatus = ActivityExecutionStatus.Canceling) OrElse (activity.ExecutionStatus = ActivityExecutionStatus.Faulting)) Then
                    flag = False
                End If
            Next i
            If Not flag Then
                Return ActivityExecutionStatus.Canceling
            End If
            Return ActivityExecutionStatus.Closed
        End Function

        Protected Overrides Function Execute(ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            Me.IsExecuting = True
            Dim i As Integer
            For i = 0 To MyBase.EnabledActivities.Count - 1
                Dim activity As Activity = MyBase.EnabledActivities.Item(i)
                activity.RegisterForStatusChange(Activity.ClosedEvent, Me)
                executionContext.ExecuteActivity(activity)
            Next i
            If (MyBase.EnabledActivities.Count <> 0) Then
                Return ActivityExecutionStatus.Executing
            End If
            Return ActivityExecutionStatus.Closed
        End Function

        Protected Overrides Sub OnActivityChangeAdd(ByVal executionContext As ActivityExecutionContext, ByVal addedActivity As Activity)
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            If (addedActivity Is Nothing) Then
                Throw New ArgumentNullException("addedActivity")
            End If
            Dim activity As ParallelActivity = [TryCast](executionContext.Activity,ParallelActivity)
            If ((activity.ExecutionStatus = ActivityExecutionStatus.Executing) AndAlso activity.IsExecuting) Then
                addedActivity.RegisterForStatusChange(Activity.ClosedEvent, Me)
                executionContext.ExecuteActivity(addedActivity)
            End If
        End Sub

        Protected Overrides Sub OnActivityChangeRemove(ByVal rootExecutionContext As ActivityExecutionContext, ByVal removedActivity As Activity)
        End Sub

        Protected Overrides Sub OnClosed(ByVal provider As IServiceProvider)
            MyBase.RemoveProperty(ParallelActivity.IsExecutingProperty)
        End Sub

        Protected Overrides Sub OnWorkflowChangesCompleted(ByVal executionContext As ActivityExecutionContext)
            MyBase.OnWorkflowChangesCompleted(executionContext)
            If Me.IsExecuting Then
                Dim flag As Boolean = True
                Dim i As Integer
                For i = 0 To MyBase.EnabledActivities.Count - 1
                    Dim activity As Activity = MyBase.EnabledActivities.Item(i)
                    If (activity.ExecutionStatus <> ActivityExecutionStatus.Closed) Then
                        flag = False
                        Exit For
                    End If
                Next i
                If flag Then
                    executionContext.CloseActivity
                End If
            End If
        End Sub

        Private Sub System.Workflow.ComponentModel.IActivityEventListener<System.Workflow.ComponentModel.ActivityExecutionStatusChangedEventArgs>.OnEvent(ByVal sender As Object, ByVal e As ActivityExecutionStatusChangedEventArgs) Implements IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs).OnEvent
            If (sender Is Nothing) Then
                Throw New ArgumentNullException("sender")
            End If
            If (e Is Nothing) Then
                Throw New ArgumentNullException("e")
            End If
            Dim context As ActivityExecutionContext = [TryCast](sender,ActivityExecutionContext)
            If (context Is Nothing) Then
                Throw New ArgumentException(SR.Error_SenderMustBeActivityExecutionContext, "sender")
            End If
            Dim activity As ParallelActivity = [TryCast](context.Activity,ParallelActivity)
            e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, Me)
            Dim flag As Boolean = True
            Dim i As Integer
            For i = 0 To activity.EnabledActivities.Count - 1
                Dim activity2 As Activity = activity.EnabledActivities.Item(i)
                If ((activity2.ExecutionStatus <> ActivityExecutionStatus.Initialized) AndAlso (activity2.ExecutionStatus <> ActivityExecutionStatus.Closed)) Then
                    flag = False
                    Exit For
                End If
            Next i
            If flag Then
                context.CloseActivity
            End If
        End Sub


        ' Properties
        Private Property IsExecuting As Boolean
            Get
                Return CBool(MyBase.GetValue(ParallelActivity.IsExecutingProperty))
            End Get
            Set(ByVal value As Boolean)
                MyBase.SetValue(ParallelActivity.IsExecutingProperty, value)
            End Set
        End Property


        ' Fields
        Private Shared IsExecutingProperty As DependencyProperty = DependencyProperty.Register("IsExecuting", GetType(Boolean), GetType(ParallelActivity), New PropertyMetadata(False))
    End Class
End Namespace

